﻿using System;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Linq;

namespace IntoNails.Models
{
    [Serializable]
    public class Person : AbstractModel<Guid>, ISerializable
    {
        #region Fields

        private string _firstName;
        private string _middleName;
        private string _lastName;

        private GenderType _gender;

        private string _address;
        private string _city;
        private string _state;
        private string _zip;

        private DateTime _dateOfBirth;

        private string _contactNumber;
        private string _cellPhone;
        private string _email;

        private string _comment;

        #endregion

        #region Constructors

        protected Person()
        {
        }

        public Person(SerializationInfo info, StreamingContext context)
        {
            this.UniqueCode = (Guid) info.GetValue("UniqueCode", typeof (Guid));
            
            #region General

            this.FirstName = info.GetString("FirstName");
            this.MiddleName = info.GetString("MiddleName");
            this.LastName = info.GetString("LastName");

            this.Gender = (GenderType) info.GetValue("Gender", typeof (GenderType));

            #endregion

            #region Address

            this.Address = info.GetString("Address");
            this.City = info.GetString("City");
            this.State = info.GetString("State");
            this.Zip = info.GetString("Zip");

            #endregion

            #region Dates

            this.DateOfBirth = info.GetDateTime("DateOfBirth");
            this.CreatedDate = info.GetDateTime("CreatedDate");
            this.UpdatedDate = info.GetDateTime("UpdatedDate");

            #endregion

            #region Contacts

            this.ContactNumber = info.GetString("ContactNumber");
            this.CellPhoneNumber = info.GetString("CellPhoneNumber");
            this.Email = info.GetString("Email");

            #endregion

            #region Reference Numbers

            ////this.SSN = info.GetString("SSN");
            ////this.ContractorNumber = info.GetString("ContractorNumber");

            #endregion
        }

	    #endregion

        #region Properties
        
        #region General

        public string FirstName
        {
            get { return this._firstName; }
            set
            {
                this._firstName = value;
                base.RaisePropertyChanged("FirstName");
            }
        }

        public string MiddleName
        {
            get { return this._middleName; }
            set
            {
                this._middleName = value;
                base.RaisePropertyChanged("MiddleName");
            }
        }

        public string LastName
        {
            get { return this._lastName; }
            set
            {
                this._lastName = value;
                base.RaisePropertyChanged("LastName");
            }
        }
        
        public GenderType Gender
        {
            get { return this._gender; }
            set
            {
                this._gender = value;
                base.RaisePropertyChanged("Gender");
            }
        }

        #endregion

        #region Address

        public string Address
        {
            get { return this._address; }
            set
            {
                this._address = value;
                base.RaisePropertyChanged("Address");
            }
        }

        public string City
        {
            get { return this._city; }
            set
            {
                this._city = value;
                base.RaisePropertyChanged("City");
            }
        }

        public string State
        {
            get { return this._state; }
            set
            {
                this._state = value;
                base.RaisePropertyChanged("State");
            }
        }

        public string Zip
        {
            get { return this._zip; }
            set
            {
                this._zip = value;
                base.RaisePropertyChanged("Zip");
            }
        }

        #endregion

        #region Dates

        public DateTime DateOfBirth
        {
            get { return this._dateOfBirth; }
            set
            {
                this._dateOfBirth = value;
                base.RaisePropertyChanged("DateOfBirth");
            }
        }
        
        #endregion

        #region Contacts

        public string ContactNumber
        {
            get { return this._contactNumber; }
            set
            {
                this._contactNumber = value;
                base.RaisePropertyChanged("ContactNumber");
            }
        }

        public string CellPhoneNumber
        {
            get { return this._cellPhone; }
            set
            {
                this._cellPhone = value;
                base.RaisePropertyChanged("CellPhoneNumber");
            }
        }

        public string Email
        {
            get { return this._email; }
            set
            {
                this._email = value;
                base.RaisePropertyChanged("Email");
            }
        }

        #endregion

        #region Others

        public string Comment
        {
            get { return this._comment; }
            set
            {
                this._comment = value;
                base.RaisePropertyChanged("Comment");
            }
        }

        #endregion

        #endregion

        #region Implementation of ISerializable

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("UniqueCode", this.UniqueCode);
            
            #region General

            info.AddValue("FirstName", this.FirstName);
            info.AddValue("MiddleName", this.MiddleName);
            info.AddValue("LastName", this.LastName);

            info.AddValue("Gender", this.Gender);

            #endregion

            #region Address

            info.AddValue("Address", this.Address);
            info.AddValue("City", this.City);
            info.AddValue("State", this.State);
            info.AddValue("Zip", this.Zip);

            #endregion

            #region Dates

            info.AddValue("DateOfBirth", this.DateOfBirth);
            info.AddValue("CreatedDate", this.CreatedDate);
            info.AddValue("UpdatedDate", this.UpdatedDate);

            #endregion

            #region Contacts

            info.AddValue("ContactNumber", this.ContactNumber);
            info.AddValue("CellPhoneNumber", this.CellPhoneNumber);
            info.AddValue("Email", this.Email);

            #endregion
            
            #region Other

            info.AddValue("IsValid", this.IsValid);

            #endregion
        }

        #endregion

        #region Object Overriden

        public override string ToString()
        {
            return string.Format("ID: {0} | Full-Name: {1} {2} {3}", this.UniqueCode, this.FirstName, this.MiddleName, this.LastName);
        }

        public override int GetHashCode()
        {
            int hashCode = 0;

            unchecked
            {
                hashCode += this.UniqueCode.GetHashCode();
                ////hashCode += !string.IsNullOrEmpty(this.DisplayName) ? this.DisplayName.GetHashCode() : 0;

                ////hashCode += !string.IsNullOrEmpty(this.FirstName) ? this.FirstName.GetHashCode() : 0;
                ////hashCode += !string.IsNullOrEmpty(this.MiddleName) ? this.MiddleName.GetHashCode() : 0;
                ////hashCode += !string.IsNullOrEmpty(this.LastName) ? this.LastName.GetHashCode() : 0;
                ////hashCode += this.Authority.GetHashCode();
                ////hashCode += this.Gender.GetHashCode();

                ////hashCode += !string.IsNullOrEmpty(this.Username) ? this.Username.GetHashCode() : 0;
                ////hashCode += !string.IsNullOrEmpty(this.Password) ? this.Password.GetHashCode() : 0;

                ////hashCode += this.Address.GetHashCode();
                ////hashCode += this.City.GetHashCode();
                ////hashCode += this.State.GetHashCode();
                ////hashCode += this.Zip.GetHashCode();

                ////hashCode += this.DateOfBirth.GetHashCode();
                ////hashCode += this.HireDate.GetHashCode();

                ////hashCode += this.ContactNumber.GetHashCode();
                ////hashCode += this.CellPhoneNumber.GetHashCode();
                ////hashCode += this.Email.GetHashCode();

                ////hashCode += this.SSN.GetHashCode();
                ////hashCode += this.ContractorNumber.GetHashCode();

                ////hashCode += this.Comment.GetHashCode();

                ////hashCode += this.CreatedDate.GetHashCode();
                ////hashCode += this.UpdatedDate.GetHashCode();
                ////hashCode += this.IsValid.GetHashCode();
            }

            return hashCode;
        }

        public override bool Equals(object obj)
        {
            User other = obj as User;
            if (other == null)
            {
                return false;
            }

            return this.UniqueCode == other.UniqueCode;
        }

        #endregion
    }
}
